1 Data Visualization Using tidyverse Package

In this note, we create sereral charts in Mankiw’s book “Macroeconomics, 7th ed., 2009”.

1.1 Setup

Sys.setenv(LANG="en")
dir.create("./data")
Warning: './data' already exists
library(tidyverse)
library(WDI)
wdi_cache <- WDIcache()
write_rds(wdi_cache, "./data/wdi_cache.RData")
wdi_cache <- read_rds("./data/wdi_cache.RData")
wdi_cache$series
wdi_cache$country

1.2 Searching and Downloading Data

WDIsearch(string = "gdp", field = "name", short = TRUE, cache = NULL)
WDIsearch(string ="", field = "name, short = FALSE, cache = wdi_cache)

1.2.1 List of Indicators

  • NY.GDP.MKTP.CD: GDP (current US$)
  • NY.GDP.DEFL.KD.ZG: Inflation, GDP deflator (annual %)
  • SL.UEM.TOTL.NE.ZS: Unemployment, total (% of total labor force) (national estimate)
  • CPTOTNSXN: CPI Price, nominal
  • SL.TLF.CACT.MA.NE.ZS: Labor force participation rate, male (% of male population ages 15+) (national estimate)
  • SL.TLF.CACT.FE.NE.ZS: Labor force participation rate, female (% of male population ages 15+) (national estimate)

1.2.2 Downloading Data

WDI(
  country = "all",
  indicator = "NY.GDP.PCAP.KD",
  start = 1960,
  end = NULL,
  extra = FALSE,
  cache = NULL,
  latest = NULL,
  language = "en"
)

1.3 FIGURES

1.3.1 1-1 Real GDP per Person in the U.S. Economy

WDIsearch(string = "gdp", field = "name", short = FALSE, cache = wdi_cache )

1.3.1.1 NY.GDP.MKTP.CD: GDP (current US$)

gdp_current <- WDI(country = "all", indicator = "NY.GDP.MKTP.CD", extra = TRUE, cache = wdi_cache)
gdp_current
gdp_current %>% filter(country == "United States") %>% 
  ggplot(aes(year, NY.GDP.MKTP.CD)) + geom_line() +
  labs(title = "Figure 1-1 Real GDP per Person in the U.S. Economy")

1.3.2 1-2 The Inflation Rate in the U.S. Economy

WDIsearch("inflation", "name",short = FALSE, cache = wdi_cache)

1.3.2.1 NY.GDP.DEFL.KD.ZG: Inflation, GDP deflator (annual %)

  • GDP Deflator: NY.GDP.DEFL.KD.ZG Inflation, GDP deflator (annual %): Inflation as measured by the annual growth rate of the GDP implicit deflator shows the rate of price change in the economy as a whole. The GDP implicit deflator is the ratio of GDP in current local currency to GDP in constant local currency.
inflation <- WDI(country = "all", indicator ="NY.GDP.DEFL.KD.ZG", extra=TRUE, cache=wdi_cache)
inflation %>% filter(country == "United States") %>% 
  ggplot(aes(year, NY.GDP.DEFL.KD.ZG)) + geom_line() +
  labs(title = "Figure 1-2 The Inflation Rate in the U.S. Economy")

1.3.3 1-3 The Unemployment Rate in the U.S. Econom

WDIsearch("unemployment", "name",short = FALSE, cache = wdi_cache)

1.3.3.1 SL.UEM.TOTL.NE.ZS: Unemployment, total (% of total labor force) (national estimate)

unemployment <- WDI(country = "all", indicator ="SL.UEM.TOTL.NE.ZS", extra=TRUE, cache=wdi_cache)
unemployment %>% filter(country == "United States") %>% 
  ggplot(aes(year, SL.UEM.TOTL.NE.ZS)) + geom_line()

1.3.4 2-3 The GDP Deflator and the CPI

WDIsearch("CPI", "name",short = FALSE, cache = wdi_cache)

1.3.4.1 CPTOTSAXNZGY: CPI Price, % y-o-y, nominal, seas. adj.

  • CPTOTSAXN: CPI Price, nominal, seas. adj.: The consumer price index reflects the change in prices for the average consumer of a constant basket of consumer goods. Data is in nominal terms and seasonally adjusted.
  • CPTOTSAXNZGY: CPI Price, % y-o-y, nominal, seas. adj.: The consumer price index reflects the change in prices for the average consumer of a constant basket of consumer goods. Data is in nominal percentage terms, measured on a year-on-year basis, and seasonally adjusted.
cpi <- WDI(country = "all", indicator ="CPTOTSAXNZGY", extra=TRUE, cache=wdi_cache)
cpi %>% filter(country == "United States") %>% 
  ggplot(aes(year, CPTOTSAXNZGY)) + geom_line()

gdp_cpi <- WDI(country = "all", indicator = c(gdp = "NY.GDP.DEFL.KD.ZG", cpi="CPTOTSAXNZGY"), extra=TRUE, cache=wdi_cache)
gdp_cpi %>% pivot_longer(c(gdp, cpi), names_to = "index", values_to = "value")
gdp_cpi %>% pivot_longer(c(gdp, cpi), names_to = "index", values_to = "value") %>%
  filter(country == "United States") %>% drop_na(value) %>%
  ggplot(aes(x = year, y = value, color = index)) + geom_line() + 
  labs(title = "Figure 2-3: The GDP Deflator and the CPI")

1.3.5 2-5 Labor-Force Participation

WDIsearch("Labor Force Participation Rate", "name",short = FALSE, cache = wdi_cache)

1.3.5.1 Indicators

  • SL.TLF.CACT.MA.NE.ZS: Labor force participation rate, male (% of male population ages 15+) (national estimate)
  • SL.TLF.CACT.FE.NE.ZS: Labor force participation rate, female (% of male population ages 15+) (national estimate)
participation <- WDI(country = "all", indicator =c(male = "SL.TLF.CACT.MA.NE.ZS", female = "SL.TLF.CACT.FE.NE.ZS"), extra=TRUE, cache=wdi_cache)
participation %>% filter(country == "United States") %>% 
  ggplot() + geom_line(aes(x = year, y = male), col = "blue") + geom_line(aes(x = year, y = female), col = "red")

participation %>% 
  pivot_longer(cols = c(male, female), names_to = "gender", values_to = "rate") %>%
  filter(country=="United States") %>% ggplot(aes(x = year, y = rate, color=gender)) + geom_line()

1.3.6 3-5 The Ratio of Labor Income to Total Income

WDIsearch(string ="", field = "name, short = FALSE, cache = wdi_cache)

1.3.6.1 Data Download

  • Indicator
df <- WDI(country = "all", indicator ="", extra=TRUE, cache=wdi_cache)

1.3.6.2 Chart

1.3.7 3-10 Military Spending and the Interest Rate in the United Kingdom

WDIsearch(string ="", field = "name, short = FALSE, cache = wdi_cache)

1.3.7.1 Data Download

  • Indicator
df <- WDI(country = "all", indicator ="", extra=TRUE, cache=wdi_cache)

1.3.7.2 Chart

1.3.8 4-1 Historical Data on U.S. Inflation and Money Growth

1.3.9 4-2 International Data on Inflation and Money Growth

1.3.10 4-3 Inflation and Nominal Interest Rates Over Time

1.3.11 4-4 Inflation and Nominal Interest Rates Across Countries

1.3.12 4-6 Money and Prices in Interwar Germany

1.3.13 5-1 Imports and Exports as a Percentage of Output: 2007

1.3.14 5-6 The Trade Balance, Saving, and Investment: The U.S. Experience

1.3.15 5-13 Inflation Differentials and the Exchange Rate

1.3.16 Big Mac Prices and the Exchange Rate: An Application of Purchasing-Power Parity

1.3.16.1 Our Big Mac index shows how burger prices are changing

1.3.17 6-1 The Unemployment Rate and the Natural Rate of Unemployment in the United States

1.3.18 Percent of Workers Covered by Collective Bargaining

1.3.19 6-4 Unemployment in Europe

1.3.20 6-5 Annual Hours Worked per Person

1.3.21 Table 7-1 International Differences in the Standard of Living

1.3.22 7-6 International Evidence on Investment Rates and Income per Person

1.3.23 7-13 International Evidence on Population Growth and Income per Person

1.3.24 Table 8-2 Growth Around the World

1.3.25 8-2 Growth in Output and the Solow Residual

1.3.26 9-1 Real GDP Growth in the United States

1.3.27 9-2 Growth in Consumption and Investment

1.3.28 9-3 Unemployment

1.3.29 9-4 Okun’s Law

1.3.30 11-2 What Happened During the Great Depression?

1.3.31 13-3 Inflation and Unemployment in the United States, 1960–2008

1.3.32 Table 13-1 Unemployment During the Volcker Disinflation

1.3.33 14-1 The Federal Funds Rate: Actual and Suggested

1.3.34 15-1 Forecasting the Recession of 1982

1.3.35 15-2 Inflation and Central-Bank Independence

1.3.36 Table 16-1 How Indebted Are the World’s Governments?

1.3.37 16-1 The Ratio of Government Debt to GDP Since 1790

1.3.38 18-1 The Three Components of Investment

1.3.39 18-4 The Stock Market and the Economy

1.3.40 18-7 The Housing Market from 2000 to 2008

1.3.41 TEMPLATE

1.3.41.1 Search String

search_string <- "gdp" # edit the search string
WDIsearch(string =search_string, field = "name, short = FALSE, cache = wdi_cache)

1.3.41.2 Line Plot with one indicator with abbriviation and one country

chosen_indicator <- "SL.UEM.TOTL.NE.ZS"
short_name <- "unemployment"
chosen_country <- "United States"
WDI(country = "all", indicator = c(short_name = chosen_indicator), extra=TRUE, cache=wdi_cache) %>%
  filter(country == chosen_country) %>% 
  ggplot(aes(year, short_name)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator, ": ", short_name, " - ", chosen_country),
       y = short_name)

1.3.41.3 Line Plot with one indicator and one country

chosen_indicator <- "SL.UEM.TOTL.NE.ZS"
chosen_country <- "United States"
WDI(country = "all", indicator = c(chosen_indicator = chosen_indicator), 
    extra=TRUE, cache=wdi_cache) %>%
  filter(country == chosen_country) %>% 
  ggplot(aes(year, chosen_indicator)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator, " - ", chosen_country), 
       y = chosen_indicator)

1.3.41.4 Line Plot with one indicator with abbriviation and several countries

chosen_indicator <- "SL.UEM.TOTL.NE.ZS"
short_name <- "unemployment"
chosen_countries <- c("United States","United Kingdom", "Japan")
WDI(country = "all", indicator = c(short_name = chosen_indicator), extra=TRUE, cache=wdi_cache) %>% drop_na(short_name) %>% 
  filter(country %in% chosen_countries) %>% 
  ggplot(aes(year, short_name, col = country)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator, ": ", short_name), y = short_name)

1.3.41.5 Line Plot with two indicators with abbriviation and one country

chosen_indicator_1 <- "NY.GDP.DEFL.KD.ZG"
short_name_1 <- "gdp"
chosen_indicator_2 <- "CPTOTSAXNZGY"
short_name_2 <- "cpi"
chosen_country <- "United States"
WDI(country = "all", indicator = c(short_name_1 = chosen_indicator_1, short_name_2 = chosen_indicator_2), extra=TRUE, cache=wdi_cache) %>% 
  filter(country == chosen_country) %>% 
  pivot_longer(c(short_name_1, short_name_2), names_to = "class", values_to = "value") %>% drop_na(value) %>%
  ggplot(aes(year, value, col = class)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator_1, ": ", short_name_1, "\n", chosen_indicator_2, ": ", short_name_2, " - ", chosen_country)) +
  scale_color_manual(labels = c(short_name_1, short_name_2), values = scales::hue_pal()(2))

chosen_indicator_1 <- "SL.TLF.CACT.MA.NE.ZS"
short_name_1 <- "male"
chosen_indicator_2 <- "SL.TLF.CACT.FE.NE.ZS"
short_name_2 <- "female"
chosen_country <- "United States"
WDI(country = "all", indicator = c(short_name_1 = chosen_indicator_1, short_name_2 = chosen_indicator_2), extra=TRUE, cache=wdi_cache) %>% 
  filter(country == chosen_country) %>% 
  pivot_longer(c(short_name_1, short_name_2), names_to = "class", values_to = "value") %>% drop_na(value) %>%
  ggplot(aes(year, value, col = class)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator_1, ": ", short_name_1, "\n", chosen_indicator_2, ": ", short_name_2, " - ", chosen_country)) +
  scale_color_manual(labels = c(short_name_1, short_name_2), values = scales::hue_pal()(2))

1.3.41.6 Line Plot with two indicators with abbriviation and several countries

chosen_indicator_1 <- "NY.GDP.DEFL.KD.ZG"
short_name_1 <- "gdp"
chosen_indicator_2 <- "CPTOTSAXNZGY"
short_name_2 <- "cpi"
chosen_countries <- c("United States", "France", "Japan")
WDI(country = "all", indicator = c(short_name_1 = chosen_indicator_1, short_name_2 = chosen_indicator_2), extra=TRUE, cache=wdi_cache) %>% 
  filter(country %in% chosen_countries) %>% 
  pivot_longer(c(short_name_1, short_name_2), names_to = "class", values_to = "value") %>% drop_na(value) %>%
  ggplot(aes(year, value, linetype = class, col = country)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator_1, ": ", short_name_1, "\n", chosen_indicator_2, ": ", short_name_2)) +
  scale_linetype_manual(labels = c(short_name_1, short_name_2), values = c("solid", "dashed"))

chosen_indicator_1 <- "SL.TLF.CACT.MA.NE.ZS"
short_name_1 <- "male"
chosen_indicator_2 <- "SL.TLF.CACT.FE.NE.ZS"
short_name_2 <- "female"
chosen_countries <- c("United States", "France", "Japan")
WDI(country = "all", indicator = c(short_name_1 = chosen_indicator_1, short_name_2 = chosen_indicator_2), extra=TRUE, cache=wdi_cache) %>% 
  filter(country %in% chosen_countries) %>% 
  pivot_longer(c(short_name_1, short_name_2), names_to = "class", values_to = "value") %>% drop_na(value) %>%
  ggplot(aes(year, value, linetype = class, col = country)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator_1, ": ", short_name_1, "\n", chosen_indicator_2, ": ", short_name_2)) +
  scale_linetype_manual(labels = c(short_name_1, short_name_2), values = c("solid", "dashed"))

1.3.41.7 Dada Download

  • Indicator(s)

1.3.41.8 Chart

1.3.41.8.1 Themes
gdp_cpi %>% pivot_longer(c(gdp, cpi), names_to = "index", values_to = "value") %>%
  filter(country == "United States") %>% drop_na(value) %>%
  ggplot(aes(x = year, y = value, color = index)) + geom_line() + 
  labs(title = "Figure 2-3: The GDP Deflator and the CPI") +
  theme_minimal()

2 Basics of R tidyverse for EDA

EDA is known as Exploratory Data Analysis. For the detail, please refer to “R for Data Scinece” by H. Wickham et. al. There are many excellent books available at the bookdown site for free. See also the arxive page.

3 References

3.1 日本語

LS0tCnRpdGxlOiAiRy4gTWFua2l3LCBNYWNyb2Vjb25vbWljcywgN3RoIEVkLiwgMjAwOSIKYXV0aG9yOiAiSC4gU3V6dWtpIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICBiZWFtZXJfcHJlc2VudGF0aW9uOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiAKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICBwb3dlcnBvaW50X3ByZXNlbnRhdGlvbjogZGVmYXVsdAogIHdvcmRfZG9jdW1lbnQ6IAogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHJlZmVyZW5jZV9kb2N4OiAicmVmX2RvYy5kb2N4IgogIGlvc2xpZGVzX3ByZXNlbnRhdGlvbjoKICAgIHdpZGVzY3JlZW46IHllcwogICAgc21hbGxlcjogeWVzCiAgc2xpZHlfcHJlc2VudGF0aW9uOiBkZWZhdWx0Ci0tLQoKIyBEYXRhIFZpc3VhbGl6YXRpb24gVXNpbmcgYHRpZHl2ZXJzZWAgUGFja2FnZQoKPiBJbiB0aGlzIG5vdGUsIHdlIGNyZWF0ZSBzZXJlcmFsIGNoYXJ0cyBpbiBNYW5raXcncyBib29rICJbTWFjcm9lY29ub21pY3MsIDd0aCBlZC4sIDIwMDldKGh0dHBzOi8vam9sbHlncmVlbmdlbmVyYWwudHlwZXBhZC5jb20vZmlsZXMvbi4tZ3JlZ29yeS1tYW5raXctbWFjcm9lY29ub21pY3MtN3RoLWVkaXRpb24tMjAwOS5wZGYpIi4KCiMjIFNldHVwCgpgYGB7ciBldmFsbD1GQUxTRX0KU3lzLnNldGVudihMQU5HPSJlbiIpCmRpci5jcmVhdGUoIi4vZGF0YSIpCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShXREkpCmBgYAoKYGBge3IgZXZhbD1GQUxTRX0Kd2RpX2NhY2hlIDwtIFdESWNhY2hlKCkKYGBgCmBgYHtyIGV2YWw9RkFMU0V9CndyaXRlX3Jkcyh3ZGlfY2FjaGUsICIuL2RhdGEvd2RpX2NhY2hlLlJEYXRhIikKYGBgCmBgYHtyfQp3ZGlfY2FjaGUgPC0gcmVhZF9yZHMoIi4vZGF0YS93ZGlfY2FjaGUuUkRhdGEiKQpgYGAKCgpgYGB7cn0Kd2RpX2NhY2hlJHNlcmllcwpgYGAKCmBgYHtyfQp3ZGlfY2FjaGUkY291bnRyeQpgYGAKCiMjIFNlYXJjaGluZyBhbmQgRG93bmxvYWRpbmcgRGF0YQoKYGBgCldESXNlYXJjaChzdHJpbmcgPSAiZ2RwIiwgZmllbGQgPSAibmFtZSIsIHNob3J0ID0gVFJVRSwgY2FjaGUgPSBOVUxMKQpgYGAKCmBgYHtyIGV2YWw9RkFMU0V9CldESXNlYXJjaChzdHJpbmcgPSIiLCBmaWVsZCA9ICJuYW1lLCBzaG9ydCA9IEZBTFNFLCBjYWNoZSA9IHdkaV9jYWNoZSkKYGBgCgoKIyMjIExpc3Qgb2YgSW5kaWNhdG9ycwoKKiBOWS5HRFAuTUtUUC5DRDogR0RQIChjdXJyZW50IFVTJCkKKiBOWS5HRFAuREVGTC5LRC5aRzogSW5mbGF0aW9uLCBHRFAgZGVmbGF0b3IgKGFubnVhbCAlKQoqIFNMLlVFTS5UT1RMLk5FLlpTOiBVbmVtcGxveW1lbnQsIHRvdGFsICglIG9mIHRvdGFsIGxhYm9yIGZvcmNlKSAobmF0aW9uYWwgZXN0aW1hdGUpCiogQ1BUT1ROU1hOOiBDUEkgUHJpY2UsIG5vbWluYWwKKiBTTC5UTEYuQ0FDVC5NQS5ORS5aUzogTGFib3IgZm9yY2UgcGFydGljaXBhdGlvbiByYXRlLCBtYWxlICglIG9mIG1hbGUgcG9wdWxhdGlvbiBhZ2VzIDE1KykgKG5hdGlvbmFsIGVzdGltYXRlKQoqIFNMLlRMRi5DQUNULkZFLk5FLlpTOiBMYWJvciBmb3JjZSBwYXJ0aWNpcGF0aW9uIHJhdGUsIGZlbWFsZSAoJSBvZiBtYWxlIHBvcHVsYXRpb24gYWdlcyAxNSspIChuYXRpb25hbCBlc3RpbWF0ZSkKCiMjIyBEb3dubG9hZGluZyBEYXRhCgpgYGAKV0RJKAogIGNvdW50cnkgPSAiYWxsIiwKICBpbmRpY2F0b3IgPSAiTlkuR0RQLlBDQVAuS0QiLAogIHN0YXJ0ID0gMTk2MCwKICBlbmQgPSBOVUxMLAogIGV4dHJhID0gRkFMU0UsCiAgY2FjaGUgPSBOVUxMLAogIGxhdGVzdCA9IE5VTEwsCiAgbGFuZ3VhZ2UgPSAiZW4iCikKYGBgCgoKCiMjIEZJR1VSRVMKCiMjIyAxLTEgUmVhbCBHRFAgcGVyIFBlcnNvbiBpbiB0aGUgVS5TLiBFY29ub215CgoKYGBge3J9CldESXNlYXJjaChzdHJpbmcgPSAiZ2RwIiwgZmllbGQgPSAibmFtZSIsIHNob3J0ID0gRkFMU0UsIGNhY2hlID0gd2RpX2NhY2hlICkKYGBgCgojIyMjIE5ZLkdEUC5NS1RQLkNEOiBHRFAgKGN1cnJlbnQgVVMkKQoKYGBge3IgY2FjaGU9VFJVRX0KZ2RwX2N1cnJlbnQgPC0gV0RJKGNvdW50cnkgPSAiYWxsIiwgaW5kaWNhdG9yID0gIk5ZLkdEUC5NS1RQLkNEIiwgZXh0cmEgPSBUUlVFLCBjYWNoZSA9IHdkaV9jYWNoZSkKYGBgCgoKYGBge3J9CmdkcF9jdXJyZW50CmBgYAoKCmBgYHtyfQpnZHBfY3VycmVudCAlPiUgZmlsdGVyKGNvdW50cnkgPT0gIlVuaXRlZCBTdGF0ZXMiKSAlPiUgCiAgZ2dwbG90KGFlcyh5ZWFyLCBOWS5HRFAuTUtUUC5DRCkpICsgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSAiRmlndXJlIDEtMSBSZWFsIEdEUCBwZXIgUGVyc29uIGluIHRoZSBVLlMuIEVjb25vbXkiKQpgYGAKCiMjIyAxLTIgVGhlIEluZmxhdGlvbiBSYXRlIGluIHRoZSBVLlMuIEVjb25vbXkKCmBgYHtyfQpXRElzZWFyY2goImluZmxhdGlvbiIsICJuYW1lIixzaG9ydCA9IEZBTFNFLCBjYWNoZSA9IHdkaV9jYWNoZSkKYGBgCgojIyMjIE5ZLkdEUC5ERUZMLktELlpHOiBJbmZsYXRpb24sIEdEUCBkZWZsYXRvciAoYW5udWFsICUpCgoqIEdEUCBEZWZsYXRvcjoKTlkuR0RQLkRFRkwuS0QuWkcgSW5mbGF0aW9uLCBHRFAgZGVmbGF0b3IgKGFubnVhbCAlKTogSW5mbGF0aW9uIGFzIG1lYXN1cmVkIGJ5IHRoZSBhbm51YWwgZ3Jvd3RoIHJhdGUgb2YgdGhlIEdEUCBpbXBsaWNpdCBkZWZsYXRvciBzaG93cyB0aGUgcmF0ZSBvZiBwcmljZSBjaGFuZ2UgaW4gdGhlIGVjb25vbXkgYXMgYSB3aG9sZS4gVGhlIEdEUCBpbXBsaWNpdCBkZWZsYXRvciBpcyB0aGUgcmF0aW8gb2YgR0RQIGluIGN1cnJlbnQgbG9jYWwgY3VycmVuY3kgdG8gR0RQIGluIGNvbnN0YW50IGxvY2FsIGN1cnJlbmN5LiAKCgpgYGB7ciBjYWNoZT1UUlVFfQppbmZsYXRpb24gPC0gV0RJKGNvdW50cnkgPSAiYWxsIiwgaW5kaWNhdG9yID0iTlkuR0RQLkRFRkwuS0QuWkciLCBleHRyYT1UUlVFLCBjYWNoZT13ZGlfY2FjaGUpCmBgYAoKYGBge3J9CmluZmxhdGlvbiAlPiUgZmlsdGVyKGNvdW50cnkgPT0gIlVuaXRlZCBTdGF0ZXMiKSAlPiUgCiAgZ2dwbG90KGFlcyh5ZWFyLCBOWS5HRFAuREVGTC5LRC5aRykpICsgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSAiRmlndXJlIDEtMiBUaGUgSW5mbGF0aW9uIFJhdGUgaW4gdGhlIFUuUy4gRWNvbm9teSIpCmBgYAoKCiMjIyAxLTMgVGhlIFVuZW1wbG95bWVudCBSYXRlIGluIHRoZSBVLlMuIEVjb25vbQoKYGBge3J9CldESXNlYXJjaCgidW5lbXBsb3ltZW50IiwgIm5hbWUiLHNob3J0ID0gRkFMU0UsIGNhY2hlID0gd2RpX2NhY2hlKQpgYGAKCiMjIyMgU0wuVUVNLlRPVEwuTkUuWlM6IFVuZW1wbG95bWVudCwgdG90YWwgKCUgb2YgdG90YWwgbGFib3IgZm9yY2UpIChuYXRpb25hbCBlc3RpbWF0ZSkKCmBgYHtyIGNhY2hlPVRSVUV9CnVuZW1wbG95bWVudCA8LSBXREkoY291bnRyeSA9ICJhbGwiLCBpbmRpY2F0b3IgPSJTTC5VRU0uVE9UTC5ORS5aUyIsIGV4dHJhPVRSVUUsIGNhY2hlPXdkaV9jYWNoZSkKYGBgCgoKYGBge3J9CnVuZW1wbG95bWVudCAlPiUgZmlsdGVyKGNvdW50cnkgPT0gIlVuaXRlZCBTdGF0ZXMiKSAlPiUgCiAgZ2dwbG90KGFlcyh5ZWFyLCBTTC5VRU0uVE9UTC5ORS5aUykpICsgZ2VvbV9saW5lKCkKYGBgCgojIyMgMi0zIFRoZSBHRFAgRGVmbGF0b3IgYW5kIHRoZSBDUEkKCmBgYHtyfQpXRElzZWFyY2goIkNQSSIsICJuYW1lIixzaG9ydCA9IEZBTFNFLCBjYWNoZSA9IHdkaV9jYWNoZSkKYGBgCgojIyMjIENQVE9UU0FYTlpHWTogQ1BJIFByaWNlLCAlIHktby15LCBub21pbmFsLCBzZWFzLiBhZGouCgoqIENQVE9UU0FYTjogQ1BJIFByaWNlLCBub21pbmFsLCBzZWFzLiBhZGouOiBUaGUgY29uc3VtZXIgcHJpY2UgaW5kZXggcmVmbGVjdHMgdGhlIGNoYW5nZSBpbiBwcmljZXMgZm9yIHRoZSBhdmVyYWdlIGNvbnN1bWVyIG9mIGEgY29uc3RhbnQgYmFza2V0IG9mIGNvbnN1bWVyIGdvb2RzLiBEYXRhIGlzIGluIG5vbWluYWwgdGVybXMgYW5kIHNlYXNvbmFsbHkgYWRqdXN0ZWQuIAoqIENQVE9UU0FYTlpHWTogQ1BJIFByaWNlLCAlIHktby15LCBub21pbmFsLCBzZWFzLiBhZGouOiBUaGUgY29uc3VtZXIgcHJpY2UgaW5kZXggcmVmbGVjdHMgdGhlIGNoYW5nZSBpbiBwcmljZXMgZm9yIHRoZSBhdmVyYWdlIGNvbnN1bWVyIG9mIGEgY29uc3RhbnQgYmFza2V0IG9mIGNvbnN1bWVyIGdvb2RzLiBEYXRhIGlzIGluIG5vbWluYWwgcGVyY2VudGFnZSB0ZXJtcywgbWVhc3VyZWQgb24gYSB5ZWFyLW9uLXllYXIgYmFzaXMsIGFuZCBzZWFzb25hbGx5IGFkanVzdGVkLgoKCmBgYHtyIGNhY2hlPVRSVUV9CmNwaSA8LSBXREkoY291bnRyeSA9ICJhbGwiLCBpbmRpY2F0b3IgPSJDUFRPVFNBWE5aR1kiLCBleHRyYT1UUlVFLCBjYWNoZT13ZGlfY2FjaGUpCmBgYAoKCmBgYHtyfQpjcGkgJT4lIGZpbHRlcihjb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIikgJT4lIAogIGdncGxvdChhZXMoeWVhciwgQ1BUT1RTQVhOWkdZKSkgKyBnZW9tX2xpbmUoKQpgYGAKCmBgYHtyfQpnZHBfY3BpIDwtIFdESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoZ2RwID0gIk5ZLkdEUC5ERUZMLktELlpHIiwgY3BpPSJDUFRPVFNBWE5aR1kiKSwgZXh0cmE9VFJVRSwgY2FjaGU9d2RpX2NhY2hlKQpgYGAKCmBgYHtyfQpnZHBfY3BpICU+JSBwaXZvdF9sb25nZXIoYyhnZHAsIGNwaSksIG5hbWVzX3RvID0gImluZGV4IiwgdmFsdWVzX3RvID0gInZhbHVlIikKYGBgCgpgYGB7cn0KZ2RwX2NwaSAlPiUgcGl2b3RfbG9uZ2VyKGMoZ2RwLCBjcGkpLCBuYW1lc190byA9ICJpbmRleCIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JQogIGZpbHRlcihjb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIikgJT4lIGRyb3BfbmEodmFsdWUpICU+JQogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSB2YWx1ZSwgY29sb3IgPSBpbmRleCkpICsgZ2VvbV9saW5lKCkgKyAKICBsYWJzKHRpdGxlID0gIkZpZ3VyZSAyLTM6IFRoZSBHRFAgRGVmbGF0b3IgYW5kIHRoZSBDUEkiKQpgYGAKCiMjIyAyLTUgTGFib3ItRm9yY2UgUGFydGljaXBhdGlvbgoKYGBge3J9CldESXNlYXJjaCgiTGFib3IgRm9yY2UgUGFydGljaXBhdGlvbiBSYXRlIiwgIm5hbWUiLHNob3J0ID0gRkFMU0UsIGNhY2hlID0gd2RpX2NhY2hlKQpgYGAKCiMjIyMgSW5kaWNhdG9ycwoKKiBTTC5UTEYuQ0FDVC5NQS5ORS5aUzogTGFib3IgZm9yY2UgcGFydGljaXBhdGlvbiByYXRlLCBtYWxlICglIG9mIG1hbGUgcG9wdWxhdGlvbiBhZ2VzIDE1KykgKG5hdGlvbmFsIGVzdGltYXRlKQoqIFNMLlRMRi5DQUNULkZFLk5FLlpTOiBMYWJvciBmb3JjZSBwYXJ0aWNpcGF0aW9uIHJhdGUsIGZlbWFsZSAoJSBvZiBtYWxlIHBvcHVsYXRpb24gYWdlcyAxNSspIChuYXRpb25hbCBlc3RpbWF0ZSkKCgpgYGB7ciBjYWNoZT1UUlVFfQpwYXJ0aWNpcGF0aW9uIDwtIFdESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9YyhtYWxlID0gIlNMLlRMRi5DQUNULk1BLk5FLlpTIiwgZmVtYWxlID0gIlNMLlRMRi5DQUNULkZFLk5FLlpTIiksIGV4dHJhPVRSVUUsIGNhY2hlPXdkaV9jYWNoZSkKYGBgCgpgYGB7cn0KcGFydGljaXBhdGlvbiAlPiUgZmlsdGVyKGNvdW50cnkgPT0gIlVuaXRlZCBTdGF0ZXMiKSAlPiUgCiAgZ2dwbG90KCkgKyBnZW9tX2xpbmUoYWVzKHggPSB5ZWFyLCB5ID0gbWFsZSksIGNvbCA9ICJibHVlIikgKyBnZW9tX2xpbmUoYWVzKHggPSB5ZWFyLCB5ID0gZmVtYWxlKSwgY29sID0gInJlZCIpCmBgYAoKCmBgYHtyfQpwYXJ0aWNpcGF0aW9uICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGMobWFsZSwgZmVtYWxlKSwgbmFtZXNfdG8gPSAiZ2VuZGVyIiwgdmFsdWVzX3RvID0gInJhdGUiKSAlPiUKICBmaWx0ZXIoY291bnRyeT09IlVuaXRlZCBTdGF0ZXMiKSAlPiUgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHJhdGUsIGNvbG9yPWdlbmRlcikpICsgZ2VvbV9saW5lKCkKYGBgCgojIyMgMy01IFRoZSBSYXRpbyBvZiBMYWJvciBJbmNvbWUgdG8gVG90YWwgSW5jb21lIAoKCmBgYHtyIGV2YWw9RkFMU0V9CldESXNlYXJjaChzdHJpbmcgPSIiLCBmaWVsZCA9ICJuYW1lLCBzaG9ydCA9IEZBTFNFLCBjYWNoZSA9IHdkaV9jYWNoZSkKYGBgCgojIyMjIERhdGEgRG93bmxvYWQKCiogSW5kaWNhdG9yCgpgYGB7ciBjYWNoZT1UUlVFLCBldmFsPUZBTFNFfQpkZiA8LSBXREkoY291bnRyeSA9ICJhbGwiLCBpbmRpY2F0b3IgPSIiLCBleHRyYT1UUlVFLCBjYWNoZT13ZGlfY2FjaGUpCmBgYAoKIyMjIyBDaGFydAoKCiMjIyAzLTEwIE1pbGl0YXJ5IFNwZW5kaW5nIGFuZCB0aGUgSW50ZXJlc3QgUmF0ZSBpbiB0aGUgVW5pdGVkIEtpbmdkb20KCmBgYHtyIGV2YWw9RkFMU0V9CldESXNlYXJjaChzdHJpbmcgPSIiLCBmaWVsZCA9ICJuYW1lLCBzaG9ydCA9IEZBTFNFLCBjYWNoZSA9IHdkaV9jYWNoZSkKYGBgCgojIyMjIERhdGEgRG93bmxvYWQKCiogSW5kaWNhdG9yCgoKYGBge3IgY2FjaGU9VFJVRSwgZXZhbD1GQUxTRX0KZGYgPC0gV0RJKGNvdW50cnkgPSAiYWxsIiwgaW5kaWNhdG9yID0iIiwgZXh0cmE9VFJVRSwgY2FjaGU9d2RpX2NhY2hlKQpgYGAKCgojIyMjIENoYXJ0CgojIyMgNC0xIEhpc3RvcmljYWwgRGF0YSBvbiBVLlMuIEluZmxhdGlvbiBhbmQgTW9uZXkgR3Jvd3RoCgojIyMgNC0yIEludGVybmF0aW9uYWwgRGF0YSBvbiBJbmZsYXRpb24gYW5kIE1vbmV5IEdyb3d0aAoKIyMjIDQtMyBJbmZsYXRpb24gYW5kIE5vbWluYWwgSW50ZXJlc3QgUmF0ZXMgT3ZlciBUaW1lCgojIyMgNC00IEluZmxhdGlvbiBhbmQgTm9taW5hbCBJbnRlcmVzdCBSYXRlcyBBY3Jvc3MgQ291bnRyaWVzCgojIyMgNC02IE1vbmV5IGFuZCBQcmljZXMgaW4gSW50ZXJ3YXIgR2VybWFueQoKIyMjIDUtMSBJbXBvcnRzIGFuZCBFeHBvcnRzIGFzIGEgUGVyY2VudGFnZSBvZiBPdXRwdXQ6IDIwMDcKCiMjIyA1LTYgVGhlIFRyYWRlIEJhbGFuY2UsIFNhdmluZywgYW5kIEludmVzdG1lbnQ6IFRoZSBVLlMuIEV4cGVyaWVuY2UKCiMjIyA1LTEzIEluZmxhdGlvbiBEaWZmZXJlbnRpYWxzIGFuZCB0aGUgRXhjaGFuZ2UgUmF0ZQoKIyMjIEJpZyBNYWMgUHJpY2VzIGFuZCB0aGUgRXhjaGFuZ2UgUmF0ZTogQW4gQXBwbGljYXRpb24gb2YgUHVyY2hhc2luZy1Qb3dlciBQYXJpdHkKCiMjIyMgT3VyIEJpZyBNYWMgaW5kZXggc2hvd3MgaG93IGJ1cmdlciBwcmljZXMgYXJlIGNoYW5naW5nCgoqIFtFY29ub21pc3QgU2l0ZV0oaHR0cHM6Ly93d3cuZWNvbm9taXN0LmNvbS9iaWctbWFjLWluZGV4KQoqIFtHaXRIdWIgU2l0ZV0oaHR0cHM6Ly9naXRodWIuY29tL1RoZUVjb25vbWlzdC9iaWctbWFjLWRhdGEpCgojIyMgNi0xIFRoZSBVbmVtcGxveW1lbnQgUmF0ZSBhbmQgdGhlIE5hdHVyYWwgUmF0ZSBvZiBVbmVtcGxveW1lbnQgaW4gdGhlIFVuaXRlZCBTdGF0ZXMKCiMjIyBQZXJjZW50IG9mIFdvcmtlcnMgQ292ZXJlZCBieSBDb2xsZWN0aXZlIEJhcmdhaW5pbmcKCiMjIyA2LTQgVW5lbXBsb3ltZW50IGluIEV1cm9wZQoKIyMjIDYtNSBBbm51YWwgSG91cnMgV29ya2VkIHBlciBQZXJzb24gCgojIyMgVGFibGUgNy0xIEludGVybmF0aW9uYWwgRGlmZmVyZW5jZXMgaW4gdGhlIFN0YW5kYXJkIG9mIExpdmluZwoKIyMjIDctNiBJbnRlcm5hdGlvbmFsIEV2aWRlbmNlIG9uIEludmVzdG1lbnQgUmF0ZXMgYW5kIEluY29tZSBwZXIgUGVyc29uCgojIyMgNy0xMyBJbnRlcm5hdGlvbmFsIEV2aWRlbmNlIG9uIFBvcHVsYXRpb24gR3Jvd3RoIGFuZCBJbmNvbWUgcGVyIFBlcnNvbgoKIyMjIFRhYmxlIDgtMiAgR3Jvd3RoIEFyb3VuZCB0aGUgV29ybGQKCiMjIyA4LTIgR3Jvd3RoIGluIE91dHB1dCBhbmQgdGhlIFNvbG93IFJlc2lkdWFsCgojIyMgOS0xIFJlYWwgR0RQIEdyb3d0aCBpbiB0aGUgVW5pdGVkIFN0YXRlcwoKIyMjIDktMiBHcm93dGggaW4gQ29uc3VtcHRpb24gYW5kIEludmVzdG1lbnQKCiMjIyA5LTMgVW5lbXBsb3ltZW50CgojIyMgOS00IE9rdW7igJlzIExhdwoKIyMjIDExLTIgV2hhdCBIYXBwZW5lZCBEdXJpbmcgdGhlIEdyZWF0IERlcHJlc3Npb24/CgojIyMgMTMtMyBJbmZsYXRpb24gYW5kIFVuZW1wbG95bWVudCBpbiB0aGUgVW5pdGVkIFN0YXRlcywgMTk2MOKAkzIwMDgKCiMjIyBUYWJsZSAxMy0xIFVuZW1wbG95bWVudCBEdXJpbmcgdGhlIFZvbGNrZXIgRGlzaW5mbGF0aW9uCgojIyMgMTQtMSBUaGUgRmVkZXJhbCBGdW5kcyBSYXRlOiBBY3R1YWwgYW5kIFN1Z2dlc3RlZAoKIyMjIDE1LTEgRm9yZWNhc3RpbmcgdGhlIFJlY2Vzc2lvbiBvZiAxOTgyIAoKIyMjIDE1LTIgSW5mbGF0aW9uIGFuZCBDZW50cmFsLUJhbmsgSW5kZXBlbmRlbmNlCgojIyMgVGFibGUgMTYtMSBIb3cgSW5kZWJ0ZWQgQXJlIHRoZSBXb3JsZOKAmXMgR292ZXJubWVudHM/CgojIyMgMTYtMSBUaGUgUmF0aW8gb2YgR292ZXJubWVudCBEZWJ0IHRvIEdEUCBTaW5jZSAxNzkwCgojIyMgMTgtMSBUaGUgVGhyZWUgQ29tcG9uZW50cyBvZiBJbnZlc3RtZW50CgojIyMgMTgtNCBUaGUgU3RvY2sgTWFya2V0IGFuZCB0aGUgRWNvbm9teQoKIyMjIDE4LTcgVGhlIEhvdXNpbmcgTWFya2V0IGZyb20gMjAwMCB0byAyMDA4CgoKCiMjIyBURU1QTEFURQoKIyMjIyBTZWFyY2ggU3RyaW5nCgpgYGB7ciBldmFsPUZBTFNFfQpzZWFyY2hfc3RyaW5nIDwtICJnZHAiICMgZWRpdCB0aGUgc2VhcmNoIHN0cmluZwpXRElzZWFyY2goc3RyaW5nID1zZWFyY2hfc3RyaW5nLCBmaWVsZCA9ICJuYW1lLCBzaG9ydCA9IEZBTFNFLCBjYWNoZSA9IHdkaV9jYWNoZSkKYGBgCgojIyMjIExpbmUgUGxvdCB3aXRoIG9uZSBpbmRpY2F0b3Igd2l0aCBhYmJyaXZpYXRpb24gYW5kIG9uZSBjb3VudHJ5CgpgYGB7cn0KY2hvc2VuX2luZGljYXRvciA8LSAiU0wuVUVNLlRPVEwuTkUuWlMiCnNob3J0X25hbWUgPC0gInVuZW1wbG95bWVudCIKY2hvc2VuX2NvdW50cnkgPC0gIlVuaXRlZCBTdGF0ZXMiCldESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoc2hvcnRfbmFtZSA9IGNob3Nlbl9pbmRpY2F0b3IpLCBleHRyYT1UUlVFLCBjYWNoZT13ZGlfY2FjaGUpICU+JQogIGZpbHRlcihjb3VudHJ5ID09IGNob3Nlbl9jb3VudHJ5KSAlPiUgCiAgZ2dwbG90KGFlcyh5ZWFyLCBzaG9ydF9uYW1lKSkgKyBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJXREkgIiwgY2hvc2VuX2luZGljYXRvciwgIjogIiwgc2hvcnRfbmFtZSwgIiAtICIsIGNob3Nlbl9jb3VudHJ5KSwKICAgICAgIHkgPSBzaG9ydF9uYW1lKQpgYGAKCiMjIyMgTGluZSBQbG90IHdpdGggb25lIGluZGljYXRvciBhbmQgb25lIGNvdW50cnkKCmBgYHtyfQpjaG9zZW5faW5kaWNhdG9yIDwtICJTTC5VRU0uVE9UTC5ORS5aUyIKY2hvc2VuX2NvdW50cnkgPC0gIlVuaXRlZCBTdGF0ZXMiCldESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoY2hvc2VuX2luZGljYXRvciA9IGNob3Nlbl9pbmRpY2F0b3IpLCAKICAgIGV4dHJhPVRSVUUsIGNhY2hlPXdkaV9jYWNoZSkgJT4lCiAgZmlsdGVyKGNvdW50cnkgPT0gY2hvc2VuX2NvdW50cnkpICU+JSAKICBnZ3Bsb3QoYWVzKHllYXIsIGNob3Nlbl9pbmRpY2F0b3IpKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIldESSAiLCBjaG9zZW5faW5kaWNhdG9yLCAiIC0gIiwgY2hvc2VuX2NvdW50cnkpLCAKICAgICAgIHkgPSBjaG9zZW5faW5kaWNhdG9yKQpgYGAKCiMjIyMgTGluZSBQbG90IHdpdGggb25lIGluZGljYXRvciB3aXRoIGFiYnJpdmlhdGlvbiBhbmQgc2V2ZXJhbCBjb3VudHJpZXMKCmBgYHtyfQpjaG9zZW5faW5kaWNhdG9yIDwtICJTTC5VRU0uVE9UTC5ORS5aUyIKc2hvcnRfbmFtZSA8LSAidW5lbXBsb3ltZW50IgpjaG9zZW5fY291bnRyaWVzIDwtIGMoIlVuaXRlZCBTdGF0ZXMiLCJVbml0ZWQgS2luZ2RvbSIsICJKYXBhbiIpCldESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoc2hvcnRfbmFtZSA9IGNob3Nlbl9pbmRpY2F0b3IpLCBleHRyYT1UUlVFLCBjYWNoZT13ZGlfY2FjaGUpICU+JSBkcm9wX25hKHNob3J0X25hbWUpICU+JSAKICBmaWx0ZXIoY291bnRyeSAlaW4lIGNob3Nlbl9jb3VudHJpZXMpICU+JSAKICBnZ3Bsb3QoYWVzKHllYXIsIHNob3J0X25hbWUsIGNvbCA9IGNvdW50cnkpKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIldESSAiLCBjaG9zZW5faW5kaWNhdG9yLCAiOiAiLCBzaG9ydF9uYW1lKSwgeSA9IHNob3J0X25hbWUpCmBgYAoKCiMjIyMgTGluZSBQbG90IHdpdGggdHdvIGluZGljYXRvcnMgd2l0aCBhYmJyaXZpYXRpb24gYW5kIG9uZSBjb3VudHJ5CgpgYGB7cn0KY2hvc2VuX2luZGljYXRvcl8xIDwtICJOWS5HRFAuREVGTC5LRC5aRyIKc2hvcnRfbmFtZV8xIDwtICJnZHAiCmNob3Nlbl9pbmRpY2F0b3JfMiA8LSAiQ1BUT1RTQVhOWkdZIgpzaG9ydF9uYW1lXzIgPC0gImNwaSIKY2hvc2VuX2NvdW50cnkgPC0gIlVuaXRlZCBTdGF0ZXMiCldESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoc2hvcnRfbmFtZV8xID0gY2hvc2VuX2luZGljYXRvcl8xLCBzaG9ydF9uYW1lXzIgPSBjaG9zZW5faW5kaWNhdG9yXzIpLCBleHRyYT1UUlVFLCBjYWNoZT13ZGlfY2FjaGUpICU+JSAKICBmaWx0ZXIoY291bnRyeSA9PSBjaG9zZW5fY291bnRyeSkgJT4lIAogIHBpdm90X2xvbmdlcihjKHNob3J0X25hbWVfMSwgc2hvcnRfbmFtZV8yKSwgbmFtZXNfdG8gPSAiY2xhc3MiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUgZHJvcF9uYSh2YWx1ZSkgJT4lCiAgZ2dwbG90KGFlcyh5ZWFyLCB2YWx1ZSwgY29sID0gY2xhc3MpKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIldESSAiLCBjaG9zZW5faW5kaWNhdG9yXzEsICI6ICIsIHNob3J0X25hbWVfMSwgIlxuIiwgY2hvc2VuX2luZGljYXRvcl8yLCAiOiAiLCBzaG9ydF9uYW1lXzIsICIgLSAiLCBjaG9zZW5fY291bnRyeSkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwobGFiZWxzID0gYyhzaG9ydF9uYW1lXzEsIHNob3J0X25hbWVfMiksIHZhbHVlcyA9IHNjYWxlczo6aHVlX3BhbCgpKDIpKQpgYGAKCmBgYHtyfQpjaG9zZW5faW5kaWNhdG9yXzEgPC0gIlNMLlRMRi5DQUNULk1BLk5FLlpTIgpzaG9ydF9uYW1lXzEgPC0gIm1hbGUiCmNob3Nlbl9pbmRpY2F0b3JfMiA8LSAiU0wuVExGLkNBQ1QuRkUuTkUuWlMiCnNob3J0X25hbWVfMiA8LSAiZmVtYWxlIgpjaG9zZW5fY291bnRyeSA8LSAiVW5pdGVkIFN0YXRlcyIKV0RJKGNvdW50cnkgPSAiYWxsIiwgaW5kaWNhdG9yID0gYyhzaG9ydF9uYW1lXzEgPSBjaG9zZW5faW5kaWNhdG9yXzEsIHNob3J0X25hbWVfMiA9IGNob3Nlbl9pbmRpY2F0b3JfMiksIGV4dHJhPVRSVUUsIGNhY2hlPXdkaV9jYWNoZSkgJT4lIAogIGZpbHRlcihjb3VudHJ5ID09IGNob3Nlbl9jb3VudHJ5KSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGMoc2hvcnRfbmFtZV8xLCBzaG9ydF9uYW1lXzIpLCBuYW1lc190byA9ICJjbGFzcyIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JSBkcm9wX25hKHZhbHVlKSAlPiUKICBnZ3Bsb3QoYWVzKHllYXIsIHZhbHVlLCBjb2wgPSBjbGFzcykpICsgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiV0RJICIsIGNob3Nlbl9pbmRpY2F0b3JfMSwgIjogIiwgc2hvcnRfbmFtZV8xLCAiXG4iLCBjaG9zZW5faW5kaWNhdG9yXzIsICI6ICIsIHNob3J0X25hbWVfMiwgIiAtICIsIGNob3Nlbl9jb3VudHJ5KSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbChsYWJlbHMgPSBjKHNob3J0X25hbWVfMSwgc2hvcnRfbmFtZV8yKSwgdmFsdWVzID0gc2NhbGVzOjpodWVfcGFsKCkoMikpCmBgYAoKIyMjIyBMaW5lIFBsb3Qgd2l0aCB0d28gaW5kaWNhdG9ycyB3aXRoIGFiYnJpdmlhdGlvbiBhbmQgc2V2ZXJhbCBjb3VudHJpZXMKCmBgYHtyfQpjaG9zZW5faW5kaWNhdG9yXzEgPC0gIk5ZLkdEUC5ERUZMLktELlpHIgpzaG9ydF9uYW1lXzEgPC0gImdkcCIKY2hvc2VuX2luZGljYXRvcl8yIDwtICJDUFRPVFNBWE5aR1kiCnNob3J0X25hbWVfMiA8LSAiY3BpIgpjaG9zZW5fY291bnRyaWVzIDwtIGMoIlVuaXRlZCBTdGF0ZXMiLCAiRnJhbmNlIiwgIkphcGFuIikKV0RJKGNvdW50cnkgPSAiYWxsIiwgaW5kaWNhdG9yID0gYyhzaG9ydF9uYW1lXzEgPSBjaG9zZW5faW5kaWNhdG9yXzEsIHNob3J0X25hbWVfMiA9IGNob3Nlbl9pbmRpY2F0b3JfMiksIGV4dHJhPVRSVUUsIGNhY2hlPXdkaV9jYWNoZSkgJT4lIAogIGZpbHRlcihjb3VudHJ5ICVpbiUgY2hvc2VuX2NvdW50cmllcykgJT4lIAogIHBpdm90X2xvbmdlcihjKHNob3J0X25hbWVfMSwgc2hvcnRfbmFtZV8yKSwgbmFtZXNfdG8gPSAiY2xhc3MiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUgZHJvcF9uYSh2YWx1ZSkgJT4lCiAgZ2dwbG90KGFlcyh5ZWFyLCB2YWx1ZSwgbGluZXR5cGUgPSBjbGFzcywgY29sID0gY291bnRyeSkpICsgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiV0RJICIsIGNob3Nlbl9pbmRpY2F0b3JfMSwgIjogIiwgc2hvcnRfbmFtZV8xLCAiXG4iLCBjaG9zZW5faW5kaWNhdG9yXzIsICI6ICIsIHNob3J0X25hbWVfMikpICsKICBzY2FsZV9saW5ldHlwZV9tYW51YWwobGFiZWxzID0gYyhzaG9ydF9uYW1lXzEsIHNob3J0X25hbWVfMiksIHZhbHVlcyA9IGMoInNvbGlkIiwgImRhc2hlZCIpKQpgYGAKCgpgYGB7cn0KY2hvc2VuX2luZGljYXRvcl8xIDwtICJTTC5UTEYuQ0FDVC5NQS5ORS5aUyIKc2hvcnRfbmFtZV8xIDwtICJtYWxlIgpjaG9zZW5faW5kaWNhdG9yXzIgPC0gIlNMLlRMRi5DQUNULkZFLk5FLlpTIgpzaG9ydF9uYW1lXzIgPC0gImZlbWFsZSIKY2hvc2VuX2NvdW50cmllcyA8LSBjKCJVbml0ZWQgU3RhdGVzIiwgIkZyYW5jZSIsICJKYXBhbiIpCldESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoc2hvcnRfbmFtZV8xID0gY2hvc2VuX2luZGljYXRvcl8xLCBzaG9ydF9uYW1lXzIgPSBjaG9zZW5faW5kaWNhdG9yXzIpLCBleHRyYT1UUlVFLCBjYWNoZT13ZGlfY2FjaGUpICU+JSAKICBmaWx0ZXIoY291bnRyeSAlaW4lIGNob3Nlbl9jb3VudHJpZXMpICU+JSAKICBwaXZvdF9sb25nZXIoYyhzaG9ydF9uYW1lXzEsIHNob3J0X25hbWVfMiksIG5hbWVzX3RvID0gImNsYXNzIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lIGRyb3BfbmEodmFsdWUpICU+JQogIGdncGxvdChhZXMoeWVhciwgdmFsdWUsIGxpbmV0eXBlID0gY2xhc3MsIGNvbCA9IGNvdW50cnkpKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIldESSAiLCBjaG9zZW5faW5kaWNhdG9yXzEsICI6ICIsIHNob3J0X25hbWVfMSwgIlxuIiwgY2hvc2VuX2luZGljYXRvcl8yLCAiOiAiLCBzaG9ydF9uYW1lXzIpKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKGxhYmVscyA9IGMoc2hvcnRfbmFtZV8xLCBzaG9ydF9uYW1lXzIpLCB2YWx1ZXMgPSBjKCJzb2xpZCIsICJkYXNoZWQiKSkKYGBgCgoKIyMjIyBEYWRhIERvd25sb2FkCgoqIEluZGljYXRvcihzKQoKYGBge3IgY2FjaGU9VFJVRSwgZWNhbD1GQUxTRX0KZGYgPC0gV0RJKGNvdW50cnkgPSAiYWxsIiwgaW5kaWNhdG9yID0iIiwgZXh0cmE9VFJVRSwgY2FjaGU9d2RpX2NhY2hlKQpgYGAKCgoKCgojIyMjIENoYXJ0CgojIyMjIyBUaGVtZXMKCiogUmVmZXJlbmNlcyB0byBUaGVtZXM6IAogIC0gW2dncGxvdDIgYm9vazogVGhlbWVzXShodHRwczovL2dncGxvdDItYm9vay5vcmcvcG9saXNoaW5nLmh0bWwjcG9saXNoaW5nKQogIC0gW2dncGxvdDIgYm9vazogQ29tcGxldGUgVGhlbWVzXShodHRwczovL2dncGxvdDItYm9vay5vcmcvcG9saXNoaW5nLmh0bWwjdGhlbWVzKQogIAoqIEV4YW1wbGU6IGB0aGVtZV9taW5pbWFsKClgCgpgYGB7cn0KZ2RwX2NwaSAlPiUgcGl2b3RfbG9uZ2VyKGMoZ2RwLCBjcGkpLCBuYW1lc190byA9ICJpbmRleCIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JQogIGZpbHRlcihjb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIikgJT4lIGRyb3BfbmEodmFsdWUpICU+JQogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSB2YWx1ZSwgY29sb3IgPSBpbmRleCkpICsgZ2VvbV9saW5lKCkgKyAKICBsYWJzKHRpdGxlID0gIkZpZ3VyZSAyLTM6IFRoZSBHRFAgRGVmbGF0b3IgYW5kIHRoZSBDUEkiKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKIyBCYXNpY3Mgb2YgUiBgdGlkeXZlcnNlYCBmb3IgRURBCgo+IEVEQSBpcyBrbm93biBhcyBFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzLiBGb3IgdGhlIGRldGFpbCwgcGxlYXNlIHJlZmVyIHRvICJbUiBmb3IgRGF0YSBTY2luZWNlXShodHRwczovL3I0ZHMuaGFkLmNvLm56KSIgYnkgSC4gV2lja2hhbSBldC4gYWwuIFRoZXJlIGFyZSBtYW55IGV4Y2VsbGVudCBib29rcyBhdmFpbGFibGUgYXQgdGhlIFtib29rZG93biBzaXRlXShodHRwczovL2Jvb2tkb3duLm9yZykgZm9yIGZyZWUuIFNlZSBhbHNvIHRoZSBbYXJ4aXZlXShodHRwczovL2Jvb2tkb3duLm9yZy9ob21lL2FyY2hpdmUvKSBwYWdlLgoKIyBSZWZlcmVuY2VzCgojIyDml6XmnKzoqp4KCiogS1VUIOioiOmHj+e1jOa4iOWtpuW/nOeUqO+8mmh0dHBzOi8veXVraXlhbmFpLmdpdGh1Yi5pby9lY29ub21ldHJpY3MyLwogKlLjgafoqIjph4/mlL/msrvlrablhaXploDvvJpodHRwczovL3Nob2hlaS1kb2kuZ2l0aHViLmlvL3F1YW50X3BvbGlzY2kvaW5kZXguaHRtbAoJLSDjgqjjg7PjgrPjg7zjg4fjgqPjg7PjgrDjgavjgaTjgYTjgabvvJpodHRwczovL3Nob2hlaS1kb2kuZ2l0aHViLmlvL3F1YW50X3BvbGlzY2kvZW5jb2Rpbmctci5odG1sI2VuY29kaW5nLXIK